package com.clouddms.controller;

import com.clouddms.entity.FileInfo;
import com.clouddms.service.storage.FileService;
import com.clouddms.service.transfer.FileTransferService;
import com.clouddms.service.security.EncryptionService;
import com.clouddms.service.common.LogService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.Resource;
import org.springframework.core.io.AbstractResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * 文件API控制器
 * 提供RESTful风格的文件管理接口
 */
@RestController
@RequestMapping("/api/files")
@CrossOrigin(origins = "*", maxAge = 3600)
public class FileApiController {

    private static final Logger logger = LoggerFactory.getLogger(FileApiController.class);

    @Autowired
    private FileService fileService;

    @Autowired
    private FileTransferService fileTransferService;

    @Autowired
    private EncryptionService encryptionService;

    @Autowired
    private LogService logService;

    /**
     * 文件上传API
     * @param file 上传的文件
     * @param userTags 用户标签（可选）
     * @param request HTTP请求
     * @return 上传结果
     */
    @PostMapping("/upload")
    public ResponseEntity<Map<String, Object>> uploadFile(
            @RequestParam("file") MultipartFile file,
            @RequestParam(value = "tags", required = false) String userTags,
            HttpServletRequest request) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            // 从请求中获取用户ID
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                response.put("success", false);
                response.put("message", "用户未认证");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            logger.info("用户 {} 上传文件: {}", userId, file.getOriginalFilename());

            // 上传文件
            FileInfo fileInfo = fileService.uploadFile(file, userId, userTags);

            // 构建响应
            response.put("success", true);
            response.put("message", "文件上传成功");
            response.put("data", buildFileInfoResponse(fileInfo));

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("文件上传失败: {}", e.getMessage(), e);
            response.put("success", false);
            response.put("message", "文件上传失败: " + e.getMessage());
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 获取用户文件列表API
     * @param includeDeleted 是否包含已删除文件
     * @param request HTTP请求
     * @return 文件列表
     */
    @GetMapping("/list")
    public ResponseEntity<Map<String, Object>> getUserFiles(
            @RequestParam(value = "includeDeleted", defaultValue = "false") boolean includeDeleted,
            HttpServletRequest request) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                response.put("success", false);
                response.put("message", "用户未认证");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            List<FileInfo> files = fileService.getUserFiles(userId, includeDeleted);
            
            response.put("success", true);
            response.put("data", files.stream()
                    .map(this::buildFileInfoResponse)
                    .toArray());
            response.put("total", files.size());

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("获取文件列表失败: {}", e.getMessage(), e);
            response.put("success", false);
            response.put("message", "获取文件列表失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 根据标签搜索文件API
     * @param tag 搜索标签
     * @param request HTTP请求
     * @return 搜索结果
     */
    @GetMapping("/search")
    public ResponseEntity<Map<String, Object>> searchFiles(
            @RequestParam("tag") String tag,
            HttpServletRequest request) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                response.put("success", false);
                response.put("message", "用户未认证");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            List<FileInfo> files = fileService.searchFilesByTag(userId, tag);
            
            response.put("success", true);
            response.put("data", files.stream()
                    .map(this::buildFileInfoResponse)
                    .toArray());
            response.put("total", files.size());
            response.put("searchTag", tag);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("搜索文件失败: {}", e.getMessage(), e);
            response.put("success", false);
            response.put("message", "搜索文件失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 文件下载API
     * @param fileId 文件ID
     * @param request HTTP请求
     * @return 文件内容
     */
    @GetMapping("/download/{fileId}")
    public ResponseEntity<Resource> downloadFile(
            @PathVariable Long fileId,
            HttpServletRequest request) {
        
        try {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
            }

            Optional<FileInfo> fileOpt = fileService.getFileById(fileId);
            if (!fileOpt.isPresent()) {
                return ResponseEntity.notFound().build();
            }

            FileInfo fileInfo = fileOpt.get();
            
            // 权限检查
            if (!fileInfo.getUserId().equals(userId)) {
                return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
            }

            // 检查文件是否可用
            if (!fileInfo.isAvailable()) {
                return ResponseEntity.status(HttpStatus.GONE).build();
            }

            // 构建文件资源
            File file = new File(fileInfo.getFilePath());
            if (!file.exists()) {
                logger.warn("文件不存在: {}", fileInfo.getFilePath());
                return ResponseEntity.notFound().build();
            }

            Resource resource;
            long contentLength;
            
            // 如果文件已加密，需要解密后再提供下载
            if (fileInfo.getIsEncrypted()) {
                logger.info("文件已加密，开始解密: {}", fileInfo.getOriginalFilename());
                
                // 创建临时解密文件
                String tempDecryptedPath = fileInfo.getFilePath() + ".decrypted.tmp";
                File tempDecryptedFile = new File(tempDecryptedPath);
                
                try {
                    // 解密文件（使用兼容的方法，从文件中读取IV）
                    boolean decryptSuccess = encryptionService.decryptFile(
                        fileInfo.getFilePath(), 
                        tempDecryptedPath
                    );
                    
                    if (!decryptSuccess) {
                        logger.error("文件解密失败: {}", fileInfo.getOriginalFilename());
                        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
                    }
                    
                    // 使用自定义Resource，自动清理临时文件
                    resource = new TempFileResource(tempDecryptedFile, fileInfo.getOriginalFilename());
                    contentLength = tempDecryptedFile.length();
                    
                    logger.info("文件解密成功: {}", fileInfo.getOriginalFilename());
                    
                } catch (Exception e) {
                    logger.error("文件解密过程中发生错误: {}", e.getMessage(), e);
                    return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
                }
            } else {
                // 文件未加密，直接提供下载
                resource = new FileSystemResource(file);
                contentLength = file.length();
            }
            
            // 设置响应头
            HttpHeaders headers = new HttpHeaders();
            headers.add(HttpHeaders.CONTENT_DISPOSITION, 
                    "attachment; filename=\"" + fileInfo.getOriginalFilename() + "\"");
            headers.add(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_OCTET_STREAM_VALUE);
            headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(contentLength));

            logger.info("用户 {} 下载文件: {}", userId, fileInfo.getOriginalFilename());
            
            // 记录下载日志
            try {
                String downloadDetails = String.format("文件名: %s, 大小: %s, 加密: %s", 
                    fileInfo.getOriginalFilename(), 
                    fileInfo.getReadableFileSize(),
                    fileInfo.getIsEncrypted() ? "是" : "否");
                logService.logFileOperation(userId, fileId, "DOWNLOAD", downloadDetails);
            } catch (Exception e) {
                logger.warn("记录下载日志失败: {}", e.getMessage());
            }
            
            return ResponseEntity.ok()
                    .headers(headers)
                    .body(resource);

        } catch (Exception e) {
            logger.error("文件下载失败: {}", e.getMessage(), e);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
        }
    }

    /**
     * 删除文件API
     * @param fileId 文件ID
     * @param request HTTP请求
     * @return 删除结果
     */
    @DeleteMapping("/{fileId}")
    public ResponseEntity<Map<String, Object>> deleteFile(
            @PathVariable Long fileId,
            @RequestParam(value = "permanent", defaultValue = "false") boolean permanent,
            HttpServletRequest request) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                response.put("success", false);
                response.put("message", "用户未认证");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            boolean success;
            String message;
            
            if (permanent) {
                success = fileService.permanentDeleteFile(fileId, userId);
                message = success ? "文件永久删除成功" : "文件永久删除失败";
            } else {
                success = fileService.deleteFile(fileId, userId);
                message = success ? "文件删除成功" : "文件删除失败";
            }
            
            if (success) {
                response.put("success", true);
                response.put("message", message);
                return ResponseEntity.ok(response);
            } else {
                response.put("success", false);
                response.put("message", message);
                return ResponseEntity.badRequest().body(response);
            }

        } catch (Exception e) {
            String errorMessage = permanent ? "永久删除文件失败" : "删除文件失败";
            logger.error("{}: {}", errorMessage, e.getMessage(), e);
            response.put("success", false);
            response.put("message", errorMessage);
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 恢复文件API
     * @param fileId 文件ID
     * @param request HTTP请求
     * @return 恢复结果
     */
    @PostMapping("/{fileId}/restore")
    public ResponseEntity<Map<String, Object>> restoreFile(
            @PathVariable Long fileId,
            HttpServletRequest request) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                response.put("success", false);
                response.put("message", "用户未认证");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            boolean success = fileService.restoreFile(fileId, userId);
            
            if (success) {
                response.put("success", true);
                response.put("message", "文件恢复成功");
                return ResponseEntity.ok(response);
            } else {
                response.put("success", false);
                response.put("message", "文件恢复失败");
                return ResponseEntity.badRequest().body(response);
            }

        } catch (Exception e) {
            logger.error("恢复文件失败: {}", e.getMessage(), e);
            response.put("success", false);
            response.put("message", "恢复文件失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 获取存储统计信息API
     * @param request HTTP请求
     * @return 存储统计信息
     */
    @GetMapping("/stats")
    public ResponseEntity<Map<String, Object>> getStorageStats(HttpServletRequest request) {
        
        Map<String, Object> response = new HashMap<>();
        
        try {
            Long userId = (Long) request.getAttribute("userId");
            if (userId == null) {
                response.put("success", false);
                response.put("message", "用户未认证");
                return ResponseEntity.status(HttpStatus.UNAUTHORIZED).body(response);
            }

            FileService.StorageStats stats = fileService.getUserStorageStats(userId);
            
            response.put("success", true);
            Map<String, Object> data = new HashMap<>();
            data.put("totalFiles", stats.getTotalFiles());
            data.put("totalSize", stats.getTotalSize());
            data.put("activeSize", stats.getActiveSize());
            data.put("deletedSize", stats.getDeletedSize());
            data.put("totalSizeFormatted", formatFileSize(stats.getTotalSize()));
            data.put("activeSizeFormatted", formatFileSize(stats.getActiveSize()));
            data.put("deletedSizeFormatted", formatFileSize(stats.getDeletedSize()));
            response.put("data", data);

            return ResponseEntity.ok(response);

        } catch (Exception e) {
            logger.error("获取存储统计失败: {}", e.getMessage(), e);
            response.put("success", false);
            response.put("message", "获取存储统计失败");
            return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body(response);
        }
    }

    /**
     * 构建文件信息响应
     */
    private Map<String, Object> buildFileInfoResponse(FileInfo fileInfo) {
        Map<String, Object> data = new HashMap<>();
        data.put("fileId", fileInfo.getFileId());
        data.put("originalFilename", fileInfo.getOriginalFilename());
        data.put("fileSize", fileInfo.getFileSize());
        data.put("fileSizeFormatted", fileInfo.getReadableFileSize());
        data.put("userTags", fileInfo.getUserTags());
        data.put("isEncrypted", fileInfo.getIsEncrypted());
        data.put("isDeleted", fileInfo.getIsDeleted());
        data.put("createdAt", fileInfo.getCreatedAt());
        data.put("updatedAt", fileInfo.getUpdatedAt());
        return data;
    }

    /**
     * 格式化文件大小
     */
    private String formatFileSize(long size) {
        if (size == 0) return "0 B";
        
        String[] units = {"B", "KB", "MB", "GB", "TB"};
        int unitIndex = 0;
        double sizeDouble = size;
        
        while (sizeDouble >= 1024 && unitIndex < units.length - 1) {
            sizeDouble /= 1024;
            unitIndex++;
        }
        
        return String.format("%.2f %s", sizeDouble, units[unitIndex]);
    }

    /**
     * 自定义Resource类，用于在使用完毕后自动清理临时文件
     */
    private static class TempFileResource extends AbstractResource {
        private static final Logger logger = LoggerFactory.getLogger(TempFileResource.class);
        private final File tempFile;
        private final String filename;

        public TempFileResource(File tempFile, String filename) {
            this.tempFile = tempFile;
            this.filename = filename;
        }

        @Override
        public String getDescription() {
            return "Temporary decrypted file: " + filename;
        }

        @Override
        public java.io.InputStream getInputStream() throws java.io.IOException {
            return new java.io.FileInputStream(tempFile) {
                @Override
                public void close() throws java.io.IOException {
                    super.close();
                    // 在流关闭后删除临时文件
                    if (tempFile.exists()) {
                        if (tempFile.delete()) {
                            logger.debug("临时解密文件已删除: {}", tempFile.getPath());
                        } else {
                            logger.warn("临时解密文件删除失败: {}", tempFile.getPath());
                        }
                    }
                }
            };
        }

        @Override
        public long contentLength() {
            return tempFile.length();
        }

        @Override
        public String getFilename() {
            return filename;
        }
    }
}